package com.example.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.base.config.auth.UserInfoShareHolder;
import com.example.demo.common.IdParam;
import com.example.demo.constants.BusinessExceptionCode;
import com.example.demo.constants.LanguageConstants;
import com.example.demo.constants.RedisKey;
import com.example.demo.constants.SubmissionSourceModuleConstant;
import com.example.demo.domain.CombineClause;
import com.example.demo.domain.SingleClause;
import com.example.demo.domain.entity.*;
import com.example.demo.domain.exam.ExamSubmitLog;
import com.example.demo.domain.exam.ExamUserScore;
import com.example.demo.domain.exam.Sorting;
import com.example.demo.dto.*;
import com.example.demo.exception.BusinessException;
import com.example.demo.exception.ExceptionUtils;
import com.example.demo.mapper.ExamUserScoreMapper;
import com.example.demo.mapper.VojLanguagesMapper;
import com.example.demo.mapper.VojProblemsMapper;
import com.example.demo.message.MessageSender;
import com.example.demo.param.voj.SubmissionCreateParam;
import com.example.demo.param.voj.SubmissionLatestQueryParam;
import com.example.demo.service.VojSubmissionsService;
import com.example.demo.mapper.VojSubmissionsMapper;
import com.example.demo.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 00774904
* @description 针对表【voj_submissions】的数据库操作Service实现
* @createDate 2023-12-18 18:23:20
*/
@Service
public class VojSubmissionsServiceImpl extends ServiceImpl<VojSubmissionsMapper, VojSubmissions>
    implements VojSubmissionsService{

    @Resource
    private VojSubmissionsMapper vojSubmissionsMapper;
    @Resource
    private VojProblemsMapper vojProblemsMapper;
    @Resource
    private MessageSender messageSender;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private VojLanguagesMapper vojLanguagesMapper;

    @Resource
    private ExamUserScoreMapper examUserScoreMapper;

    @Override
    public Long createSubmission(SubmissionCreateParam param) {

        if (StringUtils.isEmpty(param.getSourceModule())) {
            throw new BusinessException(BusinessExceptionCode.NO_SOURCE_MODULE);
        }
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long uid = user.getId();
        VojSubmissions entity = new VojSubmissions();
        entity.setProblemId(param.getProblemId());
        entity.setUid(uid);
        entity.setLanguageId(param.getLanguageId());
        entity.setSubmissionCode(param.getCode());
        entity.setSourceModule(param.getSourceModule());
        entity.setSubmissionSubmitTime(new DateTime());
        vojSubmissionsMapper.insert(entity);
        createSubmissionTask(entity.getSubmissionId());
        return entity.getSubmissionId();
    }

    @Override
    public SolveProblemCountReturnDto getSolveProblemCount() {
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long uid = user.getId();
        Long totalSolveProblemCount = vojSubmissionsMapper.getTotalSolveProblemCountByUserId(uid);
        Long totalProblemCount = vojProblemsMapper.selectCount(new QueryWrapper<>());
        List<SolveProblemCountDto> solveProblemCountGroupByProblemTagList = vojSubmissionsMapper.getSolveProblemCountGroupByProblemTag(uid);
        List<SolveProblemCountDto> problemCountGroupByProblemTagList = vojProblemsMapper.getProblemCountGroupByProblemTag();

        SolveProblemCountReturnDto result = new SolveProblemCountReturnDto();
        result.setTotalProblemCount(totalProblemCount);
        result.setTotalSolveProblemCount(totalSolveProblemCount);
        result.setProblemCountGroupByProblemTagList(problemCountGroupByProblemTagList);
        result.setSolveProblemCountGroupByProblemTagList(solveProblemCountGroupByProblemTagList);
        return result;
    }

    @Override
    // 获取提交结果
    public List<LatestSubmissionResultDto> getSubmissionResult(IdParam idParam) {
        User user = UserInfoShareHolder.getUserInfo().getUser();
        long uid = user.getId();
        List<LatestSubmissionResultDto> result = vojSubmissionsMapper.getSubmissionResult(idParam.getId(), uid, idParam.getOffset(), idParam.getSize());
        System.out.println("获取提交的结果 result:  "+ result);
        return result;
    }
    @Override
    public List<SubmissionGroupDayDto> getNumberOfSubmissionsGroupByDay(DateTime startTime, DateTime endTime, boolean isAcceptedOnly) {
        String startTimeString = DateUtil.format(DateUtil.endOfDay(startTime), "yyyy-MM-dd HH:mm:ss");
        String endTimeString = DateUtil.format(DateUtil.endOfDay(endTime), "yyyy-MM-dd HH:mm:ss");
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long uid = user.getId();
        List<SubmissionGroupDayDto> result = vojSubmissionsMapper.getNumberOfSubmissionsGroupByDay(startTimeString, endTimeString, uid, isAcceptedOnly);
        return result;
    }

    @Override
    public List<SubmissionGroupDayLanguageDto> getNumberOfSubmissionsGroupByDayAndLanguage(DateTime startTime, DateTime endTime, boolean isAcceptedOnly) {
        String startTimeString = DateUtil.format(DateUtil.endOfDay(startTime), "yyyy-MM-dd HH:mm:ss");
        String endTimeString = DateUtil.format(DateUtil.endOfDay(endTime), "yyyy-MM-dd HH:mm:ss");
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long uid = user.getId();
        List<SubmissionGroupDayLanguageDto> submissions = vojSubmissionsMapper.getNumberOfSubmissionsGroupByDayAndLanguage(startTimeString, endTimeString, uid, isAcceptedOnly);

        List<VojLanguages> vojLanguages = vojLanguagesMapper.selectList(new QueryWrapper<>());
        if (CollectionUtil.isEmpty(submissions) || CollectionUtil.isEmpty(vojLanguages)) {
            return submissions;
        }
        Map<Integer, String> languageMap = vojLanguages.stream().collect(Collectors.toMap(VojLanguages::getLanguageId, VojLanguages::getLanguageName));

        submissions.parallelStream().forEach(item -> {
            item.setLanguage(languageMap.get(item.getLanguageId()));
        });
        return submissions;
    }

    @Override
    public SubmissionPeriodReturnDto getNumberOfSubmissionsGroupByMonth(Date startTime, Date endTime) {
        String startTimeString = DateUtil.format(DateUtil.endOfDay(startTime), "yyyy-MM-dd HH:mm:ss");
        String endTimeString = DateUtil.format(DateUtil.endOfDay(endTime), "yyyy-MM-dd HH:mm:ss");
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long uid = user.getId();
        List<SubmissionGroupDayDto> totalList = vojSubmissionsMapper.getNumberOfSubmissionsGroupByMonth(startTimeString, endTimeString, uid, false);
        List<SubmissionGroupDayDto> acList = vojSubmissionsMapper.getNumberOfSubmissionsGroupByMonth(startTimeString, endTimeString, uid, true);
        SubmissionPeriodReturnDto result = new SubmissionPeriodReturnDto();
        result.setTotalList(totalList);
        result.setAcList(acList);
        return result;
    }

    @Override
    public Page<LatestSubmissionResultDto> getLatestSubmissions(SubmissionLatestQueryParam param) {
        Page<LatestSubmissionResultDto> result = new Page<>();
        result.setCurrent(param.getCurrent());
        result.setSize(param.getSize());
        List<LatestSubmissionResultDto> list = vojSubmissionsMapper.getLatestSubmissionsList(param, param.getOffset());
        if (!CollectionUtil.isEmpty(list)){
            List<VojLanguages> vojLanguages = vojLanguagesMapper.selectList(new QueryWrapper<>());
            if (!CollectionUtil.isEmpty(vojLanguages)){
                Map<Integer, String> languageMap = vojLanguages.stream().collect(Collectors.toMap(VojLanguages::getLanguageId, VojLanguages::getLanguageName));
                list.stream().forEach(item -> {
                    item.setLanguageName(languageMap.get(item.getLanguageId()));
                });
            }
        }
        result.setRecords(list);
        Long total = vojSubmissionsMapper.getLatestSubmissionsCount(param);
        result.setTotal(total);

        return result;
    }
    @Override
    public LatestSubmissionResultDto getSubmitLogBySubmissionId(Long submissionId) {
        LatestSubmissionResultDto latestSubmissionResultDto = BeanUtil.copyProperties(vojSubmissionsMapper.selectById(submissionId), LatestSubmissionResultDto.class);
        VojLanguages vojLanguages = vojLanguagesMapper.selectById(latestSubmissionResultDto.getLanguageId());
        latestSubmissionResultDto.setLanguageName(vojLanguages.getLanguageName());
        return latestSubmissionResultDto;
    }

    @Override
    public List<LatestSubmissionResultDto> getQuestionSubmitLog(Long questionID, Long examId) {
        User user = UserInfoShareHolder.getUserInfo().getUser();
        Long userId = user.getId();
        if (questionID == null) {
            throw ExceptionUtils.exception("查询评测记录问题ID标识不能为空");
        }
        if (examId == null) {
            throw ExceptionUtils.exception("查询评测记录考试ID标识不能为空");
        }
        ExamUserScore examUserScore = examUserScoreMapper.selectOne(new LambdaQueryWrapper<ExamUserScore>()
                .eq(ExamUserScore::getUserId, userId)
                .eq(ExamUserScore::getExamId, examId));
        LambdaQueryWrapper<VojSubmissions> vojSubmissionsLambdaQueryWrapper = new LambdaQueryWrapper<VojSubmissions>()
                .eq(VojSubmissions::getUid, userId)
                .eq(VojSubmissions::getProblemId, questionID)
                .eq(VojSubmissions::getSourceModule, "exam")
                .gt(VojSubmissions::getSubmissionExecuteTime, new Date(examUserScore.getEnterTime().getTime()))
                .orderByDesc(VojSubmissions::getSubmissionSubmitTime);

        List<VojSubmissions> vojSubmissions = vojSubmissionsMapper.selectList(vojSubmissionsLambdaQueryWrapper);
        List<LatestSubmissionResultDto> list = new ArrayList<>();
        vojSubmissions.forEach(e -> list.add(BeanUtil.copyProperties(e,LatestSubmissionResultDto.class)));
        if (!CollectionUtil.isEmpty(list)){
            List<VojLanguages> vojLanguages = vojLanguagesMapper.selectList(new QueryWrapper<>());
            if (!CollectionUtil.isEmpty(vojLanguages)){
                Map<Integer, String> languageMap = vojLanguages.stream().collect(Collectors.toMap(VojLanguages::getLanguageId, VojLanguages::getLanguageName));
                list.stream().forEach(item -> {
                    item.setLanguageName(languageMap.get(item.getLanguageId()));
                });
            }
        }
        System.out.println("latestSubmissionResultDtos"+list);
        return list;
    }



    /**
     * 生成提交消息进MQ
     * @param submissionId
     */
    private void createSubmissionTask(long submissionId) {
        Map<String, Object> mapMessage = new HashMap<>();
        mapMessage.put("event", "SubmissionCreated");
        mapMessage.put("submissionId", submissionId);
        messageSender.sendMessage(mapMessage);
    }
}




